package com.example.starter.security.util;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.example.starter.security.pojo.ExampleUser;
import com.example.starter.webmvc.util.WebUtil;
import lombok.experimental.UtilityClass;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.security.oauth2.provider.token.TokenStore;

import java.util.Optional;

/**
 * @author 王令
 * @since 2022/8/9 22:46
 */
@UtilityClass
public class SecurityUtil {

    /**
     * 获取Authentication
     */
    public Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    public String getUsername() {
        return Optional.ofNullable(getUser()).map(ExampleUser::getUsername).orElse(null);
    }

    public boolean LOGGED() {
        Authentication authentication = getAuthentication();
        return ObjUtil.isNotNull(authentication) && !(authentication instanceof AnonymousAuthenticationToken);
    }

    private TokenStore getTokenStore() {
        return SpringUtil.getBean(TokenStore.class);
    }

    private OAuth2AuthenticationDetails getOAuth2AuthenticationDetails() {
        return LOGGED() ? (OAuth2AuthenticationDetails) Optional.ofNullable(getAuthentication())
                .map(Authentication::getDetails).orElse(null) : null;
    }

    private String getTokenValue() {
        return Optional.ofNullable(getOAuth2AuthenticationDetails()).map(OAuth2AuthenticationDetails::getTokenValue)
                .orElse(null);
    }


    private OAuth2Authentication readAuthentication() {
        return Optional.ofNullable(getTokenStore()).map(tokenStore -> tokenStore.readAuthentication(getTokenValue()))
                .orElse(null);
    }

    /**
     * 当前登录用户
     */
    public ExampleUser getUser() {
        ExampleUser user =
                (ExampleUser) Optional.ofNullable(readAuthentication()).map(OAuth2Authentication::getPrincipal)
                        .orElse(null);
        if (ObjUtil.isNotNull(user)) {
            user.setTenantId(WebUtil.getTenantId());
            user.setPassword(null);
        }
        return user;
    }
}
